package com.huawei.esdk.tp.healthcare.local.impl.service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.xml.ws.Holder;

import org.apache.cxf.common.util.StringUtils;
import org.apache.log4j.Logger;

import com.huawei.esdk.platform.professional.local.PlatformServiceFactoryEx;
import com.huawei.esdk.platform.professional.local.bean.SDKResponse;
import com.huawei.esdk.platform.professional.local.constant.PlatformNativeConstant;
import com.huawei.esdk.platform.professional.local.impl.utils.RSA2048Utils;
import com.huawei.esdk.platform.professional.local.service.common.PlatformKeyServiceEx;
import com.huawei.esdk.tp.healthcare.local.bean.ConferenceInfo;
import com.huawei.esdk.tp.healthcare.local.bean.TPSDKResponse;
import com.huawei.esdk.tp.healthcare.local.conference.ConferenceService;
import com.huawei.esdk.tp.healthcare.local.impl.autogen.ConfSitesStatusMap;
import com.huawei.esdk.tp.healthcare.local.impl.autogen.TPHealthcareConfCtr;
import com.huawei.esdk.tp.healthcare.local.impl.autogen.TPHealthcareConfMgr;
import com.huawei.esdk.tp.healthcare.local.impl.utils.AES128Utils;
import com.huawei.esdk.tp.healthcare.local.impl.utils.Base64Utils;
import com.huawei.esdk.tp.healthcare.local.impl.utils.ClientProvider;
import com.huawei.esdk.tp.healthcare.local.impl.utils.ExceptionUtils;

public class ConferenceServiceImpl implements ConferenceService {
	private TPHealthcareConfMgr tPHealthcareConfMgr = ((TPHealthcareConfMgr) ClientProvider
			.getClient(TPHealthcareConfMgr.class));
	private TPHealthcareConfCtr tPHealthcareConfCtr = ((TPHealthcareConfCtr) ClientProvider
			.getClient(TPHealthcareConfCtr.class));
	private static ConferenceServiceImpl instance = null;
	
	private static final Logger LOGGER = Logger.getLogger(ConferenceServiceImpl.class);
	
	private PlatformKeyServiceEx keyServiceEx = PlatformServiceFactoryEx.getService(PlatformKeyServiceEx.class);
	
	public static synchronized ConferenceServiceImpl getInstance()
	{
		if (null == instance) {
			instance = new ConferenceServiceImpl();
		}
		return instance;
	}
	
	public TPSDKResponse<ConferenceInfo> scheduleConf(
			ConferenceInfo scheduleConf) {
	    TPSDKResponse<ConferenceInfo> conferenceInfoResp = new TPSDKResponse<ConferenceInfo>();
	    
	    LOGGER.info("begin to execute getPublicKey method");
        SDKResponse<String> key = keyServiceEx.getPublicKey("RSA2048");
        if (null == key || 0 != key.getResultCode())
        {
            LOGGER.info("failed to get publicKey");
            conferenceInfoResp.setResultCode(PlatformNativeConstant.FAILED_TO_GET_PUTLIC_KEY);
            return conferenceInfoResp;
        }
        LOGGER.info("execute getPublicKey method completed");
        
        Integer setSecretKeyResultCode = setSecretKey();
        if (null == setSecretKeyResultCode || 0 != setSecretKeyResultCode)
        {
            conferenceInfoResp.setResultCode(PlatformNativeConstant.FAILED_TO_SET_SECRET_KEY);
            return conferenceInfoResp;
        }
	    
	    if (null != scheduleConf && !StringUtils.isEmpty(scheduleConf.getPassword()))
        {
            String encrytedPassword;
            try
            {
                encrytedPassword = Base64Utils.encode(AES128Utils.encode(scheduleConf.getPassword().getBytes("UTF-8")));
                scheduleConf.setPassword(encrytedPassword);
            }
            catch (Exception e)
            {
                LOGGER.debug("encode password error");
                conferenceInfoResp.setResultCode(PlatformNativeConstant.SDK_TP_PASSWORD_ENCODE_ERRORCODE);
                return conferenceInfoResp;
            }
        }
        
        if (null != scheduleConf && !StringUtils.isEmpty(scheduleConf.getChairmanPassword()))
        {
            String encrytedChairmanPassword;
            try
            {
                encrytedChairmanPassword = Base64Utils.encode(AES128Utils.encode(scheduleConf.getChairmanPassword().getBytes("UTF-8")));
                scheduleConf.setChairmanPassword(encrytedChairmanPassword);
            }
            catch (Exception e)
            {
                LOGGER.debug("encode ChairmanPassword error");
                conferenceInfoResp.setResultCode(PlatformNativeConstant.SDK_TP_PASSWORD_ENCODE_ERRORCODE);
                return conferenceInfoResp;
            }
        }
        
		
		Holder<Integer> sdkResponse = new Holder<Integer>();
		Holder<ConferenceInfo> conferenceInfo = new Holder<ConferenceInfo>();
		try {
			tPHealthcareConfMgr.scheduleConf(scheduleConf, sdkResponse,
					conferenceInfo);
		} catch (Exception e) {
			ExceptionUtils.processSoapException(conferenceInfoResp, e);
			return conferenceInfoResp;
		}
		Integer resultCode = sdkResponse.value;
		conferenceInfoResp.setResult(0 == resultCode ? conferenceInfo.value : null);
		conferenceInfoResp.setResultCode(resultCode);
		return conferenceInfoResp;
	}

	
	public TPSDKResponse<ConferenceInfo> scheduleDynamicSiteConf(
			ConferenceInfo scheduleConf) {
	    
	    TPSDKResponse<ConferenceInfo> conferenceInfoResp = new TPSDKResponse<ConferenceInfo>();
	    
	    LOGGER.info("begin to execute getPublicKey method");
        SDKResponse<String> key = keyServiceEx.getPublicKey("RSA2048");
        if (null == key || 0 != key.getResultCode())
        {
            LOGGER.info("failed to get publicKey");
            conferenceInfoResp.setResultCode(PlatformNativeConstant.FAILED_TO_GET_PUTLIC_KEY);
            return conferenceInfoResp;
        }
        LOGGER.info("execute getPublicKey method completed");
        
        Integer setSecretKeyResultCode = setSecretKey();
        if (null == setSecretKeyResultCode || 0 != setSecretKeyResultCode)
        {
            conferenceInfoResp.setResultCode(PlatformNativeConstant.FAILED_TO_SET_SECRET_KEY);
            return conferenceInfoResp;
        }
	    
	    if (null != scheduleConf && !StringUtils.isEmpty(scheduleConf.getPassword()))
        {
            String encrytedPassword;
            try
            {
                encrytedPassword = Base64Utils.encode(AES128Utils.encode(scheduleConf.getPassword().getBytes("UTF-8")));
                scheduleConf.setPassword(encrytedPassword);
            }
            catch (Exception e)
            {
                LOGGER.debug("encode password error");
                conferenceInfoResp.setResultCode(PlatformNativeConstant.SDK_TP_PASSWORD_ENCODE_ERRORCODE);
                return conferenceInfoResp;
            }
        }
        
        if (null != scheduleConf && !StringUtils.isEmpty(scheduleConf.getChairmanPassword()))
        {
            String encrytedChairmanPassword;
            try
            {
                encrytedChairmanPassword = Base64Utils.encode(AES128Utils.encode(scheduleConf.getChairmanPassword().getBytes("UTF-8")));
                scheduleConf.setChairmanPassword(encrytedChairmanPassword);
            }
            catch (Exception e)
            {
                LOGGER.debug("encode ChairmanPassword error");
                conferenceInfoResp.setResultCode(PlatformNativeConstant.SDK_TP_PASSWORD_ENCODE_ERRORCODE);
                return conferenceInfoResp;
            }
        }
	    
        
		
		Holder<Integer> sdkResponse = new Holder<Integer>();
		Holder<ConferenceInfo> conferenceInfo = new Holder<ConferenceInfo>();
		try {
			tPHealthcareConfMgr.scheduleDynamicSiteConf(scheduleConf,
					sdkResponse, conferenceInfo);
		} catch (Exception e) {
			ExceptionUtils.processSoapException(conferenceInfoResp, e);
			return conferenceInfoResp;
		}
		Integer resultCode = sdkResponse.value;
		conferenceInfoResp.setResult(0 == resultCode ? conferenceInfo.value : null);
		conferenceInfoResp.setResultCode(resultCode);
		return conferenceInfoResp;
	}

	
	public TPSDKResponse<String> addSiteToScheduledConf(String confId,
			String siteUri) {
		TPSDKResponse<String> resp = new TPSDKResponse<String>();
		Holder<Integer> sdkResponse = new Holder<Integer>();
		Holder<String> confAccessCode = new Holder<String>();
		try {
			tPHealthcareConfMgr.addSiteToScheduledConf(confId, siteUri,
					sdkResponse, confAccessCode);
		} catch (Exception e) {
			ExceptionUtils.processSoapException(resp, e);
			return resp;
		}
		Integer resultCode = sdkResponse.value;
		resp.setResult(0 == resultCode ? confAccessCode.value : null);
		resp.setResultCode(resultCode);
		return resp;
	}

	
	public Integer delSiteFromScheduledConf(String confId, String siteUri) {
		try {
			return tPHealthcareConfMgr
					.delSiteFromScheduledConf(confId, siteUri);
		} catch (Exception e) {
			return ExceptionUtils.processSoapException(e);
		}
	}

	
	public Integer cancelScheduledConf(String confId) {
		try {
			return tPHealthcareConfMgr.cancelScheduledConf(confId);
		} catch (Exception e) {
			return ExceptionUtils.processSoapException(e);
		}
	}

	
	public Integer proLongScheduledConf(String confId, Integer prolongTime) {
		try {
			return tPHealthcareConfMgr
					.prolongScheduledConf(confId, prolongTime);
		} catch (Exception e) {
			return ExceptionUtils.processSoapException(e);
		}
	}

	
	public TPSDKResponse<ConferenceInfo> editScheduledConf(
			ConferenceInfo editConf) {
	    TPSDKResponse<ConferenceInfo> conferenceInfoResp = new TPSDKResponse<ConferenceInfo>();
	    
	    LOGGER.info("begin to execute getPublicKey method");
        SDKResponse<String> key = keyServiceEx.getPublicKey("RSA2048");
        if (null == key || 0 != key.getResultCode())
        {
            LOGGER.info("failed to get publicKey");
            conferenceInfoResp.setResultCode(PlatformNativeConstant.FAILED_TO_GET_PUTLIC_KEY);
            return conferenceInfoResp;
        }
        LOGGER.info("execute getPublicKey method completed");
        
        Integer setSecretKeyResultCode = setSecretKey();
        if (null == setSecretKeyResultCode || 0 != setSecretKeyResultCode)
        {
            conferenceInfoResp.setResultCode(PlatformNativeConstant.FAILED_TO_SET_SECRET_KEY);
            return conferenceInfoResp;
        }
	    
	    if (null != editConf && !StringUtils.isEmpty(editConf.getPassword()))
        {
            String encrytedPassword;
            try
            {
                encrytedPassword = Base64Utils.encode(AES128Utils.encode(editConf.getPassword().getBytes("UTF-8")));
                editConf.setPassword(encrytedPassword);
            }
            catch (Exception e)
            {
                LOGGER.debug("encode password error");
                conferenceInfoResp.setResultCode(PlatformNativeConstant.SDK_TP_PASSWORD_ENCODE_ERRORCODE);
                return conferenceInfoResp;
            }
        }
        
        if (null != editConf && !StringUtils.isEmpty(editConf.getChairmanPassword()))
        {
            String encrytedChairmanPassword;
            try
            {
                encrytedChairmanPassword = Base64Utils.encode(AES128Utils.encode(editConf.getChairmanPassword().getBytes("UTF-8")));
                editConf.setChairmanPassword(encrytedChairmanPassword);
            }
            catch (Exception e)
            {
                LOGGER.debug("encode ChairmanPassword error");
                conferenceInfoResp.setResultCode(PlatformNativeConstant.SDK_TP_PASSWORD_ENCODE_ERRORCODE);
                return conferenceInfoResp;
            }
        }
	    
		
		Holder<Integer> sdkResponse = new Holder<Integer>();
		Holder<ConferenceInfo> conferenceInfo = new Holder<ConferenceInfo>();
		try {
			tPHealthcareConfMgr.editScheduledConf(editConf, sdkResponse,
					conferenceInfo);
		} catch (Exception e) {
			ExceptionUtils.processSoapException(conferenceInfoResp, e);
			return conferenceInfoResp;
		}
		Integer resultCode = sdkResponse.value;
		conferenceInfoResp.setResult(0 == resultCode ? conferenceInfo.value : null);
		conferenceInfoResp.setResultCode(resultCode);
		return conferenceInfoResp;
	}

	
	public TPSDKResponse<Map<String, Integer>> queryConfSitesStatus(
			String confId, List<String> siteUris) {
		TPSDKResponse<Map<String, Integer>> resp = new TPSDKResponse<Map<String, Integer>>();
		Holder<Integer> sdkResponse = new Holder<Integer>();
		Holder<List<ConfSitesStatusMap>> confSitesStatus = new Holder<List<ConfSitesStatusMap>>();
		try {
			tPHealthcareConfMgr.queryConfSitesStatus(confId, siteUris,
					sdkResponse, confSitesStatus);
		} catch (Exception e) {
			ExceptionUtils.processSoapException(resp, e);
			return resp;
		}
		Integer resultCode = sdkResponse.value;
		resp.setResultCode(resultCode);
		if (0 == resultCode) {
			Map<String, Integer> map = new HashMap<String, Integer>();
			for (ConfSitesStatusMap status : confSitesStatus.value) {
				map.put(status.getSiteUri(), status.getConfSiteStatus());
			}
			resp.setResult(map);
		}
		return resp;
	}

	
	public Integer endConf(String confId) {
		try {
			return tPHealthcareConfCtr.endConf(confId);
		} catch (Exception e) {
			return ExceptionUtils.processSoapException(e);
		}
	}

	
	public Integer addSiteToConf(String confId, String siteUri) {
		try {
			return tPHealthcareConfCtr.addSiteToConf(confId, siteUri);
		} catch (Exception e) {
			return ExceptionUtils.processSoapException(e);
		}
	}

	
	public Integer delSiteFromConf(String confId, String siteUri) {
		try {
			return tPHealthcareConfCtr.delSiteFromConf(confId, siteUri);
		} catch (Exception e) {
			return ExceptionUtils.processSoapException(e);
		}
	}

	
	public Integer setAudioSwitch(String confId, Boolean onOff) {
		try {
			return tPHealthcareConfCtr.setAudioSwitch(confId, onOff);
		} catch (Exception e) {
			return ExceptionUtils.processSoapException(e);
		}
	}

	
	public TPSDKResponse<ConferenceInfo> scheduleImmediateConf(
			ConferenceInfo scheduleConf) {
	    TPSDKResponse<ConferenceInfo> resp = new TPSDKResponse<ConferenceInfo>();
	    
	    LOGGER.info("begin to execute getPublicKey method");
        SDKResponse<String> key = keyServiceEx.getPublicKey("RSA2048");
        if (null == key || 0 != key.getResultCode())
        {
            LOGGER.info("failed to get publicKey");
            resp.setResultCode(PlatformNativeConstant.FAILED_TO_GET_PUTLIC_KEY);
            return resp;
        }
        LOGGER.info("execute getPublicKey method completed");
        
        Integer setSecretKeyResultCode = setSecretKey();
        if (null == setSecretKeyResultCode || 0 != setSecretKeyResultCode)
        {
            resp.setResultCode(PlatformNativeConstant.FAILED_TO_SET_SECRET_KEY);
            return resp;
        }
	    
	    if (null != scheduleConf && !StringUtils.isEmpty(scheduleConf.getPassword()))
        {
            String encrytedPassword;
            try
            {
                encrytedPassword = Base64Utils.encode(AES128Utils.encode(scheduleConf.getPassword().getBytes("UTF-8")));
                scheduleConf.setPassword(encrytedPassword);
            }
            catch (Exception e)
            {
                LOGGER.debug("encode password error");
                resp.setResultCode(PlatformNativeConstant.SDK_TP_PASSWORD_ENCODE_ERRORCODE);
                return resp;
            }
        }
        
        if (null != scheduleConf && !StringUtils.isEmpty(scheduleConf.getChairmanPassword()))
        {
            String encrytedChairmanPassword;
            try
            {
                encrytedChairmanPassword = Base64Utils.encode(AES128Utils.encode(scheduleConf.getChairmanPassword().getBytes("UTF-8")));
                scheduleConf.setChairmanPassword(encrytedChairmanPassword);
            }
            catch (Exception e)
            {
                LOGGER.debug("encode ChairmanPassword error");
                resp.setResultCode(PlatformNativeConstant.SDK_TP_PASSWORD_ENCODE_ERRORCODE);
                return resp;
            }
        }
        
		
		Holder<Integer> sdkResponse = new Holder<Integer>();
        Holder<ConferenceInfo> conferenceInfo = new Holder<ConferenceInfo>();
		try {
			tPHealthcareConfMgr.scheduleImmediateConf(scheduleConf, sdkResponse, conferenceInfo);
		} catch (Exception e) {
			ExceptionUtils.processSoapException(resp, e);
			return resp;
		}
		Integer resultCode = sdkResponse.value;
		resp.setResult(0 == resultCode ? conferenceInfo.value : null);
		resp.setResultCode(resultCode);
		return resp;
	}

	
	public TPSDKResponse<Integer> queryConferenceStatus(String confId) {
		TPSDKResponse<Integer> resp = new TPSDKResponse<Integer>();
		Holder<Integer> sdkResponse = new Holder<Integer>();
        Holder<Integer> conferenceStatus = new Holder<Integer>();
		try {
			tPHealthcareConfMgr.queryConferenceStatus(confId,sdkResponse,conferenceStatus);
		} catch (Exception e) {
			ExceptionUtils.processSoapException(resp,e);
			return resp;
		}
		Integer resultCode = sdkResponse.value;
		resp.setResult(0 == resultCode ? conferenceStatus.value : null);
		resp.setResultCode(resultCode);
		return resp;
	}
	
    private Integer setSecretKey()
    {
        LOGGER.info("begin to execute setSecretKey method");
        byte[] secretKey = AES128Utils.getBT_KEY();
        byte[] iv = AES128Utils.getBT_IV();
        Integer resultCode = null;
        try
        {
            String secretKeyStr =
                Base64Utils.encode(RSA2048Utils.encode(AES128Utils.byte2Hex(secretKey).getBytes("UTF-8")));
            String ivStr = Base64Utils.encode(RSA2048Utils.encode(AES128Utils.byte2Hex(iv).getBytes("UTF-8")));
            
            resultCode = keyServiceEx.setSecretKey("AES128", secretKeyStr, ivStr);
        }
        catch (Exception e)
        {
            LOGGER.info("failed to setSecretKey");
            resultCode = PlatformNativeConstant.FAILED_TO_SET_SECRET_KEY;
        }
        LOGGER.info("execute setSecretKey method completed");
        return resultCode;
    }

}
